package net.skystudio.es.service.impl;

import lombok.extern.slf4j.Slf4j;
import net.skystudio.es.common.PageBean;
import net.skystudio.es.entity.ItemDesc;
import net.skystudio.es.service.ItemDescService;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Order(1)
@Slf4j
@Service("itemDescForEs")
public class ItemDescForEsServiceImpl implements ItemDescService {

    @Autowired
    private RestHighLevelClient client;

    @Autowired
    private HotWordServiceImpl hotWordService;

    @Override
    public List<ItemDesc> findBySearch(String key) {
        List<ItemDesc> result = new ArrayList<>();
        SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 添加高亮显示
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");
        highlightBuilder.field("title").field("content");
        sourceBuilder.highlighter(highlightBuilder);

        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        if (StringUtils.isNotBlank(key)) {
            //查询
            MultiMatchQueryBuilder multiMatchQueryBuilder = new MultiMatchQueryBuilder(key, "title", "content");
            boolQueryBuilder.must(multiMatchQueryBuilder);
        } else {
            boolQueryBuilder.must(new MatchAllQueryBuilder());
        }
        sourceBuilder.query(boolQueryBuilder);
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse;
        try {
            searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            log.info("查询hit条数:{}", searchResponse.getHits().getTotalHits().value);
            log.info("查询数据:{}", Arrays.toString(searchResponse.getHits().getHits()));
        } catch (IOException e) {
            throw new RuntimeException();
        }
        SearchHit[] hits = searchResponse.getHits().getHits();
        Arrays.stream(hits).forEach(s -> {
            Map<String, Object> sourceAsMap = s.getSourceAsMap();

            Map<String, HighlightField> highlightFields = s.getHighlightFields();
            ItemDesc itemDesc = new ItemDesc();
            itemDesc.setId(sourceAsMap.get("id").toString());
            itemDesc.setTitle(highlightFields.get("title") == null ? sourceAsMap.get("title").toString() :
                    highlightFields.get("title").getFragments()[0].string());
            itemDesc.setContent(highlightFields.get("content") == null ? sourceAsMap.get("content").toString() : highlightFields.get("content").getFragments()[0].string());

//            Map<String, Object> sourceAsMap = s.getSourceAsMap();
//            ItemDesc itemDesc = BeansUtil.wrapBean(ItemDesc.class, sourceAsMap);
            result.add(itemDesc);
        });
        return result;
    }

    @Override
    public PageBean<ItemDesc> pageQuery(Integer page, Integer size, String key) {
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        if (StringUtils.isNotBlank(key)) {
            //查询
            MultiMatchQueryBuilder multiMatchQueryBuilder = new MultiMatchQueryBuilder(key, "title", "content");
            boolQueryBuilder.must(multiMatchQueryBuilder);
        } else {
            boolQueryBuilder.must(new MatchAllQueryBuilder());
        }

        SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 添加高亮显示
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");
        highlightBuilder.field("title").field("content");
        sourceBuilder.highlighter(highlightBuilder);

        // 聚合统计
//        TermsAggregationBuilder aggregation = AggregationBuilders.terms("item-aggregate")
//                .field("title");
//        sourceBuilder.aggregation(aggregation);

        sourceBuilder.query(boolQueryBuilder);
        sourceBuilder.from((page - 1) > 0 ? (page - 1) * size : 0);
        sourceBuilder.size(size);
        sourceBuilder.sort("_id", SortOrder.ASC);
        searchRequest.source(sourceBuilder);

        SearchResponse searchResponse;
        List<String> hotWords;
        try {
            searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
//            hotWords = fetchHotWords(searchResponse);
        } catch (IOException e) {
            throw new RuntimeException();
        }
        List<ItemDesc> result = new ArrayList<>();
        SearchHit[] hits = searchResponse.getHits().getHits();
        Arrays.stream(hits).forEach(s -> {
            Map<String, Object> sourceAsMap = s.getSourceAsMap();

            Map<String, HighlightField> highlightFields = s.getHighlightFields();
            ItemDesc itemDesc = new ItemDesc();
            itemDesc.setId(sourceAsMap.get("id").toString());
            itemDesc.setTitle(highlightFields.get("title") == null ? sourceAsMap.get("title").toString() :
                    highlightFields.get("title").getFragments()[0].string());
            itemDesc.setContent(highlightFields.get("content") == null ? sourceAsMap.get("content").toString() : highlightFields.get("content").getFragments()[0].string());

//            Map<String, Object> sourceAsMap = s.getSourceAsMap();
//            ItemDesc itemDesc = BeansUtil.wrapBean(ItemDesc.class, sourceAsMap);
            result.add(itemDesc);
        });
        PageImpl<ItemDesc> resultPage = new PageImpl<>(result, PageRequest.of(page, size),
                searchResponse.getHits().getTotalHits().value);
        PageBean pageBean = new PageBean();
        pageBean.setDatas(resultPage.getContent());
        pageBean.setTotalRow(resultPage.getTotalElements());
        pageBean.setPageNum(resultPage.getNumber());
        pageBean.setPageSize(resultPage.getSize());
        pageBean.setTotalPage(resultPage.getTotalPages());
//        pageBean.setHotWords(hotWordService.topTen(key));
        return pageBean;
    }

    private List<String> fetchHotWords(SearchResponse searchResponse) {
        //获取搜索日志
//        SearchRequestBuilder requestBuilder = client.prepareSearch("index").setTypes("log").setQuery(QueryBuilders.matchAllQuery());
//        //聚合分析查询出现次数最多的10个词汇
//        SearchResponse actionGet = requestBuilder.addAggregation(AggregationBuilders.terms("hotWord").field("keywords").size(10)).execute().actionGet();
        //获取分析后的数据
//        Aggregations aggregations = SearchResponse searchResponse.getAggregations();

        Aggregations aggregations = searchResponse.getAggregations();
        Terms trem = aggregations.get("item-aggregate");
        List<? extends Terms.Bucket> buckets = trem.getBuckets();
        List<String> hotWords = new ArrayList<>();
        for (Terms.Bucket bucket : buckets) {
            String key = (String) bucket.getKey();
            hotWords.add(key);
        }
        return hotWords;
    }

}

